package com.john.http.core.parser.config;

import com.john.http.core.convert.IValueConverter;
import com.john.http.core.convert.Trim2NullValueConverter;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.TreeMap;

/**
 * 〈一句话功能简述〉<br/>
 * 〈解析HTML配置信息〉
 *
 * @author jiangguangtao on 2016/4/28.
 */
public class HtmlParseConfig {
    //从哪儿开始，或者说要解释的部分
    private String containerSelector;
    //每一行数据选择器
    private String rowSelector;
    //每一列数据选择器
    private String colSelector;
    //标题行数，标识要路过的行数
    private int headRows = 0;
    private Map<Integer, HtmlParseConfigItem> configItemMap = new TreeMap<Integer, HtmlParseConfigItem>();

    private HtmlParseConfig() {
    }

    public static HtmlParseConfig build() {
        return new HtmlParseConfig();
    }

    /**
     * @param containerSelector 代理数据所在父容器CSS选择器
     * @return
     */
    public HtmlParseConfig containerSelector(String containerSelector) {
        this.containerSelector = containerSelector;
        return this;
    }

    /**
     * 通过此选择器查询出所有的行节点
     *
     * @param rowSelector 在数据容器内，行数据CSS选择器
     * @return
     */
    public HtmlParseConfig rowSelector(String rowSelector) {
        this.rowSelector = rowSelector;
        return this;
    }

    /**
     * 通过此选择器过滤出行中所有的列节点
     *
     * @param colSelector 在行中选择列的CSS选择器
     * @return
     */
    public HtmlParseConfig colSelector(String colSelector) {
        this.colSelector = colSelector;
        return this;
    }

    /**
     * 在数据窗口内要跳过的行数目录
     *
     * @param headRows 标题行数
     * @return
     */
    public HtmlParseConfig headRows(int headRows) {
        this.headRows = headRows >= 0 ? headRows : 0;
        return this;
    }

    /**
     * 映射一个简单的配置属性
     * <p>直接获取列HTML节点的字符串值并设置到field上</p>
     *
     * @param colIndex  此字段所在列序号
     * @param fieldName 映射到的字段名称
     * @return
     */
    public HtmlParseConfig fieldMapping(int colIndex, String fieldName) {
        return fieldMapping(colIndex, fieldName, new Trim2NullValueConverter());
    }

    /**
     * 映射一个简单的配置属性
     * <p>直接获取列HTML节点的字符串值并设置到field上</p>
     *
     * @param colIndex       此字段所在列序号
     * @param fieldName      映射到的字段名称
     * @param valueConverter 值转换器
     * @return
     */
    public HtmlParseConfig fieldMapping(int colIndex, String fieldName, IValueConverter valueConverter) {
        return fieldMapping(colIndex, fieldName, valueConverter, null);
    }

    /**
     * 映射指定列序号的值到字段值上
     * <p>首先通过valueSelector找到值所有在节点，再取节点的字符串值</p>
     *
     * @param colIndex       此字段所在列序号
     * @param fieldName      映射到的字段名称
     * @param valueConverter 值转换器
     * @param valueSelector  值所有节点所选器，如果值直接存在于列节点上，此值为空
     * @return
     */
    public HtmlParseConfig fieldMapping(int colIndex, String fieldName,
                                        IValueConverter valueConverter, String valueSelector) {

        return fieldMapping(colIndex, fieldName, valueConverter, valueSelector, null);
    }

    /**
     * 映射指定列序号的值到字段值上
     * <p>首先通过valueSelector找到值所有在节点，再通过valueAttr找到相应的值</p>
     *
     * @param colIndex
     * @param fieldName
     * @param valueConverter
     * @param valueSelector  值所有节点所选器，如果值直接存在于列节点上，此值为空
     * @param valueAttr      值所在节点的属性名称，值不是节点的文本值时使用，其它情况传入空
     * @return
     */
    public HtmlParseConfig fieldMapping(int colIndex, String fieldName,
                                        IValueConverter valueConverter, String valueSelector, String valueAttr) {
        HtmlParseConfigItem pgci = new HtmlParseConfigItem();
        pgci.setIndex(colIndex);
        pgci.setField(fieldName);
        pgci.setValueConvert(valueConverter);
        pgci.setValueSelector(StringUtils.trimToNull(valueSelector));
        pgci.setValueAttr(StringUtils.trimToNull(valueAttr));
        configItemMap.put(colIndex, pgci);

        return this;
    }

    public String getContainerSelector() {
        return containerSelector;
    }

    public String getRowSelector() {
        return rowSelector;
    }

    public String getColSelector() {
        return colSelector;
    }

    public int getHeadRows() {
        return headRows;
    }

    /**
     * 指定列序号是否映射了字段
     *
     * @param colIndex
     * @return
     */
    public boolean isColMapped(int colIndex) {
        return configItemMap.containsKey(colIndex);
    }

    /**
     * 获取指定列的配置信息
     *
     * @param colIndex
     * @return null如果不存在
     */
    public HtmlParseConfigItem getConfigItem(int colIndex) {
        return configItemMap.get(colIndex);
    }
}
